/**
 * Similarity Search 2012
 * Binary Branch Filter for Tree Edit Distance
 * @author Peter K�a
 */
package treeedit;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Map.Entry;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

public class Utils {
	/**
	 * Load file from disk.
	 * 
	 * @param filepath
	 *            path to the desired file
	 * @return file retrieved from the disk
	 */
	public static File loadFileFromDisk(final String filepath) {
		try {
			return new File(filepath);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Save file to disk.
	 * 
	 * @param filepath
	 *            path to the desired file
	 * @param content 
	 * 			  content to be saved to the file           
	 * @return success
	 */
	public static boolean saveFileToDisk(final String filepath, final String content) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filepath));
			out.write(content);
			out.close();
			return true;
		} catch (IOException e) {
			System.out.println("Save file failed");			
			return false;
		}
	}

	/**
	 * Produce debug output of a given matrix
	 * 
	 * @param matrix
	 *            2 dimensional array to be printed out
	 * @return String containing human readable content of the provided 2D array
	 */
	public static String debugOutput(final int[][] matrix) {
		StringBuilder sb = new StringBuilder();
		String newline = System.getProperty("line.separator");

		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[0].length; j++) {
				sb.append(matrix[i][j] + " ");
			}

			sb.append(newline);
		}
		return sb.toString();
	}

	public static String debugOutput(final Document dom) {
		Transformer transformer;
		try {
			transformer = TransformerFactory.newInstance().newTransformer();

			transformer.setOutputProperty(OutputKeys.INDENT, "yes");

			// initialize StreamResult with File object to save to file
			StreamResult result = new StreamResult(new StringWriter());
			DOMSource source = new DOMSource(dom);
			transformer.transform(source, result);

			String xmlString = result.getWriter().toString();
			return xmlString;
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
		return null;

	}

	public static String getIndent(final int indent) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < indent; i++) {
			sb.append('\t');
		}
		return sb.toString();
	}

	public static void printArray(int[] array) {
		printArray(array, 0, array.length - 1);
	}

	public static void printArray(int[] array, int start, int end) {
		for (int i = start; i <= end; i++) {
			System.out.print(array[i]);
			if (i != end)
				System.out.print(",");
		}
		System.out.println();
	}

	public static void printTree(Tree tree) {
		System.out.print("[" + tree.getName() + "");
		if (!tree.isLeaf()) {
			System.out.print("<");
			for (Tree child : tree.getChildren())
				printTree(child);
			System.out.print(">");
		}
		System.out.print("]");
	}

	public static void printNBTree(NBTree tree) {
		System.out.print("[" + tree.getName() + "");
		if (!tree.isEmpty()) {
			System.out.print("<");
			if (tree.getLeft() != null)
				printNBTree(tree.getLeft());
			if (tree.getRight() != null)
				printNBTree(tree.getRight());
			System.out.print(">");
		}
		System.out.print("]");
	}

	public static void printHashtable(Hashtable<?, ?> ht) {
		if (ht == null)
			return;
		System.out.println("Hashtable output [" + ht.size() + "]:");
		for (Entry<?, ?> pair : ht.entrySet()) {
			System.out.println(pair.getKey() + " -> " + pair.getValue());
		}
	}

	public static String getHashtableToString(Hashtable<?, ?> ht) {
		if (ht == null)
			return "";
		StringBuilder sb = new StringBuilder("Hashtable output [" + ht.size() + "]:");
		for (Entry<?, ?> pair : ht.entrySet()) {
			sb.append(String.format("%s->%s\n", pair.getKey(), pair.getValue()));
		}
		return sb.toString();
	}

	public static String convertPreorderTree(Tree t) {
		StringBuilder sb = new StringBuilder(t.getName());
		if (!t.isLeaf()) {
			for (Tree c : t.getChildren()) {
				sb.append(convertPreorderTree(c));
			}
		}
		return sb.toString();
	}

	public static String convertPostorderTree(Tree t, String tmp) {
		if (t.isLeaf()) {
			return tmp += t.getName();
		} else {
			for (Tree c : t.getChildren()) {
				tmp = convertPostorderTree(c, tmp);
			}
		}
		return tmp + t.getName();
	}

}
